package guda.house.biz.impl;

import guda.grape.autogen.common.page.BaseQuery;
import guda.grape.autogen.common.page.BizResult;
import guda.grape.util.Convert;
import guda.house.biz.AdminBiz;
import guda.house.biz.beans.vo.AdminVO;
import guda.house.biz.beans.vo.AdminVillageVO;
import guda.house.biz.beans.vo.RoleVO;
import guda.house.biz.beans.vo.VillageVO;
import guda.house.biz.constants.CommonResultCode;
import guda.house.biz.enums.RoleEnum;
import guda.house.biz.form.AdminEditForm;
import guda.house.biz.form.AdminForm;
import guda.house.biz.form.AdminVillageForm;
import guda.house.biz.form.LoginForm;
import guda.house.biz.query.AdminQuery;
import guda.house.biz.query.AdminVillageQuery;
import guda.house.biz.query.RoleQuery;
import guda.house.biz.query.VillageQuery;
import guda.house.biz.util.ArrayUtil;
import guda.house.biz.util.Md5Util;
import guda.house.biz.util.Transform;
import guda.house.biz.util.TransformHelper;
import guda.house.dal.dao.*;
import guda.house.dal.dataobject.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.*;

public class AdminBizImpl implements AdminBiz {

    private final static Logger logger = LoggerFactory.getLogger(AdminBizImpl.class);

    @Autowired
    private AdminDAO adminDAO;
    @Autowired
    private RoleDAO roleDAO;
    @Autowired
    private VillageDAO villageDAO;
    @Autowired
    private AdminVillageRelDAO adminVillageRelDAO;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private AdminRoleRelDAO adminRoleRelDAO;
    @Autowired
    private RoleResourceRelDAO roleResourceRelDAO;
    @Autowired
    private ResourceDAO resourceDAO;

    public BizResult detail(long id) {
        BizResult bizResult = new BizResult();
        try {
            AdminDO adminDO = adminDAO.getAdminById(id);
            bizResult.data.put("adminDO", adminDO);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("query Admin error", e);
        }
        return bizResult;
    }

    public BizResult list(BaseQuery baseQuery) {
        BizResult bizResult = new BizResult();
        try {
            int totalCount = adminDAO.countForPage(baseQuery);
            baseQuery.setTotalCount(totalCount);
            List<AdminDO> adminList = adminDAO.selectForPage(baseQuery);
            RoleQuery roleQuery = new RoleQuery();
            roleQuery.setPageSize(100);
            List<RoleDO> roleDOs = roleDAO.selectForPage(roleQuery);
            Map<Long, RoleDO> map = new HashMap<Long, RoleDO>();
            for (RoleDO roleDO : roleDOs) {
                map.put(roleDO.getRoleId(), roleDO);
            }
            List<AdminVO> adminVOList = new ArrayList<AdminVO>(adminList.size());
            for (AdminDO adminDO : adminList) {
                AdminVO adminVO = new AdminVO();
                adminVO.setAdminDO(adminDO);
                List<AdminRoleRelDO> adminRoleRelDOs = adminRoleRelDAO.selectByAdminId(adminDO.getAdminId());
                List<RoleDO> roleDOList = new ArrayList<RoleDO>();
                for (AdminRoleRelDO adminRoleRelDO : adminRoleRelDOs) {
                    roleDOList.add(map.get(adminRoleRelDO.getRoleId()));
                }
                adminVO.setRoleDOList(roleDOList);
                adminVOList.add(adminVO);
            }
            bizResult.data.put("adminVOList", adminVOList);
            bizResult.data.put("query", baseQuery);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("view Admin list error", e);
        }
        return bizResult;
    }

    public BizResult delete(long id) {
        BizResult bizResult = new BizResult();
        try {
            adminDAO.delAdminById(id);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("delete admin error", e);
        }
        return bizResult;
    }

    public BizResult create(final AdminForm adminForm) {
        final BizResult bizResult = new BizResult();
        final AdminDO adminDO = adminForm.toDO();
        try {
            //判断是否重名
            AdminQuery adminQuery = new AdminQuery();
            adminQuery.setLoginName(adminDO.getLoginName());
            int i = adminDAO.countForPage(adminQuery);
            if (i > 0) {
                bizResult.code = CommonResultCode.NAME_REPEAT;
                return bizResult;
            }
            adminDO.setLoginPassword(Md5Util.md5(adminDO.getLoginPassword()));
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                    long id = adminDAO.insert(adminDO);
                    if (adminForm.getRoleIdArray() != null) {
                        for (String s : adminForm.getRoleIdArray()) {
                            long roleId = Convert.toLong(s);
                            AdminRoleRelDO adminRoleDO = new AdminRoleRelDO();
                            adminRoleDO.setRoleId(roleId);
                            adminRoleDO.setAdminId(id);
                            adminRoleRelDAO.insert(adminRoleDO);
                        }
                    }
                    bizResult.data.put("id", id);
                }
            });


            bizResult.success = true;
        } catch (Exception e) {
            logger.error("create Admin error", e);
        }
        return bizResult;
    }

    @Override
    public BizResult update(final AdminEditForm adminEditForm) {
        BizResult bizResult = new BizResult();
        final AdminDO adminDO = adminEditForm.toDO();
        try {
            //判断是否重名
            AdminQuery adminQuery = new AdminQuery();
            adminQuery.setLoginName(adminDO.getLoginName());
            List<AdminDO> adminDOs = adminDAO.selectForPage(adminQuery);
            if (adminDOs.size() > 1) {
                bizResult.code = CommonResultCode.NAME_REPEAT;
                return bizResult;
            } else if (adminDOs.size() == 1) {
                if (adminDOs.get(0).getAdminId().longValue() != adminDO.getAdminId().longValue()) {
                    bizResult.code = CommonResultCode.NAME_REPEAT;
                    return bizResult;
                }
            }
            if (adminDO.getLoginPassword() != null && adminDO.getLoginPassword().length() != 32) {
                adminDO.setLoginPassword(Md5Util.md5(adminDO.getLoginPassword()));
            }

            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                    adminDAO.updateByIdSelective(adminDO);
                    adminRoleRelDAO.delByAdminId(adminDO.getAdminId());
                    if (adminEditForm.getRoleIdArray() != null) {
                        for (String s : adminEditForm.getRoleIdArray()) {
                            long roleId = Convert.toLong(s);
                            AdminRoleRelDO adminRoleDO = new AdminRoleRelDO();
                            adminRoleDO.setRoleId(roleId);
                            adminRoleDO.setAdminId(adminDO.getAdminId());
                            adminRoleRelDAO.insert(adminRoleDO);
                        }
                    }
                }
            });


            bizResult.success = true;
        } catch (Exception e) {
            logger.error("update Admin error", e);
        }
        return bizResult;
    }

    @Override
    public BizResult login(LoginForm loginForm) {
        BizResult bizResult = new BizResult();
        AdminDO adminDO = adminDAO.selectByUser(loginForm.getUsername(), Md5Util.md5(loginForm.getPassword()));
        if (adminDO == null) {
            return bizResult;
        }
        List<AdminRoleRelDO> adminRoleRelDOs = adminRoleRelDAO.selectByAdminId(adminDO.getAdminId());
        Set<Long> roleIdSet = TransformHelper.transform2Set(adminRoleRelDOs, new Transform<AdminRoleRelDO, Long>() {
            @Override
            public Long transform(AdminRoleRelDO object) {
                return object.getRoleId();
            }
        });
        if (roleIdSet.size() > 0) {
            List<RoleDO> roleByIds = roleDAO.getRoleByIds(new ArrayList(roleIdSet));
            Set<String> roleNameSet = TransformHelper.transform2Set(roleByIds, new Transform<RoleDO, String>() {
                @Override
                public String transform(RoleDO object) {
                    return object.getRoleName();
                }
            });
            List<RoleResourceRelDO> roleResourceRelDOs = roleResourceRelDAO.selectByRoleId(new ArrayList<Long>(roleIdSet));
            List<Long> resourceIdList = TransformHelper.transform(roleResourceRelDOs, new Transform<RoleResourceRelDO, Long>() {
                @Override
                public Long transform(RoleResourceRelDO object) {
                    return object.getResourceId();
                }
            });
            if(resourceIdList.size()>0) {
                List<ResourceDO> resourceByIds = resourceDAO.getResourceByIds(resourceIdList);
                List<String> resourceList= TransformHelper.transform(resourceByIds, new Transform<ResourceDO, String>() {
                    @Override
                    public String transform(ResourceDO object) {
                        return object.getResourceUrl();
                    }
                });
                bizResult.data.put("resourceList",resourceList);
            }

            bizResult.data.put("roleNameArray", roleNameSet.toArray(new String[]{}));
            if (roleNameSet.contains(RoleEnum.admin.name())) {
                VillageQuery villageQuery = new VillageQuery();
                villageQuery.setPageSize(500);
                List<VillageDO> villageDOs = villageDAO.selectForPage(villageQuery);
                List<Long> villageIdList = TransformHelper.transform(villageDOs, new Transform<VillageDO, Long>() {
                    @Override
                    public Long transform(VillageDO object) {
                        return object.getVillageId();
                    }
                });
                List<VillageVO> villageVOList = new ArrayList<VillageVO>(villageDOs.size());
                for (VillageDO villageDO : villageDOs) {
                    VillageVO villageVO = new VillageVO();
                    villageVO.setVillageId(villageDO.getVillageId());
                    villageVO.setVillageName(villageDO.getVillageName());
                    villageVOList.add(villageVO);
                }
                bizResult.data.put("villageVOList", villageVOList);
                bizResult.data.put("villageIdList", villageIdList);
            }else{
                AdminVillageQuery adminVillageQuery = new AdminVillageQuery();
                adminVillageQuery.setAdminId(adminDO.getAdminId());
                adminVillageQuery.setPageSize(500);
                List<AdminVillageRelDO> adminVillageRelDOs = adminVillageRelDAO.selectForPage(adminVillageQuery);
                Set<Long> villageIdSet = TransformHelper.transform2Set(adminVillageRelDOs, new Transform<AdminVillageRelDO, Long>() {
                    @Override
                    public Long transform(AdminVillageRelDO object) {
                        return object.getVillageId();
                    }
                });
                if (villageIdSet.size() > 0) {
                    List<VillageDO> villageByIds = villageDAO.getVillageByIds(new ArrayList(villageIdSet));
                    List<VillageVO> villageVOList = new ArrayList<VillageVO>(villageByIds.size());
                    for (VillageDO villageDO : villageByIds) {
                        VillageVO villageVO = new VillageVO();
                        villageVO.setVillageId(villageDO.getVillageId());
                        villageVO.setVillageName(villageDO.getVillageName());
                        villageVOList.add(villageVO);
                    }
                    bizResult.data.put("villageVOList", villageVOList);
                    bizResult.data.put("villageIdList", new ArrayList<Long>(villageIdSet));
                }
            }
        } else {
            AdminVillageQuery adminVillageQuery = new AdminVillageQuery();
            adminVillageQuery.setAdminId(adminDO.getAdminId());
            adminVillageQuery.setPageSize(500);
            List<AdminVillageRelDO> adminVillageRelDOs = adminVillageRelDAO.selectForPage(adminVillageQuery);
            Set<Long> villageIdSet = TransformHelper.transform2Set(adminVillageRelDOs, new Transform<AdminVillageRelDO, Long>() {
                @Override
                public Long transform(AdminVillageRelDO object) {
                    return object.getVillageId();
                }
            });
            if (villageIdSet.size() > 0) {
                List<VillageDO> villageByIds = villageDAO.getVillageByIds(new ArrayList(villageIdSet));
                List<VillageVO> villageVOList = new ArrayList<VillageVO>(villageByIds.size());
                for (VillageDO villageDO : villageByIds) {
                    VillageVO villageVO = new VillageVO();
                    villageVO.setVillageId(villageDO.getVillageId());
                    villageVO.setVillageName(villageDO.getVillageName());
                    villageVOList.add(villageVO);
                }
                bizResult.data.put("villageVOList", villageVOList);
                bizResult.data.put("villageIdList", new ArrayList<Long>(villageIdSet));
            }

        }



        bizResult.data.put("admin", adminDO);
        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult queryForCreate() {
        BizResult bizResult = new BizResult();
        RoleQuery roleQuery = new RoleQuery();
        roleQuery.setPageSize(100);
        List<RoleDO> roleDOs = roleDAO.selectForPage(roleQuery);
        bizResult.data.put("roleList", roleDOs);
        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult queryForEdit(long id) {
        BizResult bizResult = new BizResult();
        try {
            AdminDO adminDO = adminDAO.getAdminById(id);
            bizResult.data.put("adminDO", adminDO);
            RoleQuery roleQuery = new RoleQuery();
            roleQuery.setPageSize(100);
            List<RoleDO> roleDOs = roleDAO.selectForPage(roleQuery);
            List<AdminRoleRelDO> adminRoleRelDOs = adminRoleRelDAO.selectByAdminId(adminDO.getAdminId());
            Set<Long> roleIdSet = TransformHelper.transform2Set(adminRoleRelDOs, new Transform<AdminRoleRelDO, Long>() {
                @Override
                public Long transform(AdminRoleRelDO object) {
                    return object.getRoleId();
                }
            });
            String[] roles  = new String[roleIdSet.size()];
            Object[] objects = roleIdSet.toArray();
            int i=0;
            for(Object obj:objects){
                roles[i] = String.valueOf(obj);
                ++i;
            }

            bizResult.data.put("roleIdArray", roles);
            bizResult.data.put("roleList", roleDOs);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("query Admin error", e);
        }
        return bizResult;
    }

    @Override
    public BizResult queryAllVillage(long id) {
        BizResult bizResult = new BizResult();
        AdminVillageQuery adminVillageQuery = new AdminVillageQuery();
        adminVillageQuery.setAdminId(id);
        adminVillageQuery.setPageSize(500);
        List<AdminVillageRelDO> adminVillageRelDOs = adminVillageRelDAO.selectForPage(adminVillageQuery);
        Set<Long> villageIdSet = TransformHelper.transform2Set(adminVillageRelDOs, new Transform<AdminVillageRelDO, Long>() {
            @Override
            public Long transform(AdminVillageRelDO object) {
                return object.getVillageId();
            }
        });
        VillageQuery villageQuery = new VillageQuery();
        villageQuery.setPageSize(500);
        List<VillageDO> villageDOs = villageDAO.selectForPage(villageQuery);
        List<AdminVillageVO> adminVillageVOList = new ArrayList<AdminVillageVO>(villageDOs.size());
        for (VillageDO villageDO : villageDOs) {
            AdminVillageVO adminVillageVO = new AdminVillageVO();
            adminVillageVO.setVillageDO(villageDO);
            if (villageIdSet.contains(villageDO.getVillageId())) {
                adminVillageVO.setBinded(true);
            }
            adminVillageVOList.add(adminVillageVO);
        }
        bizResult.data.put("adminVillageVOList", adminVillageVOList);
        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult bindVillage(final AdminVillageForm adminVillageForm) {
        BizResult bizResult = new BizResult();
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                for (Long villageId : adminVillageForm.getVillageIdList()) {

                    AdminVillageRelDO adminVillageRel = adminVillageRelDAO.getAdminVillageRel(adminVillageForm.getAdminId(), villageId);
                    if (adminVillageRel == null) {
                        adminVillageRel = new AdminVillageRelDO();
                        adminVillageRel.setVillageId(villageId);
                        adminVillageRel.setAdminId(adminVillageForm.getAdminId());
                        adminVillageRelDAO.insert(adminVillageRel);
                    }
                }
            }
        });

        bizResult.success = true;
        return bizResult;
    }


}
